<?php declare(strict_types=1);

/**
 * @author      guosir
 * @copyright   2023-2025 owner
 **/

namespace Srv\Apps\Apis\Content\Ctl;

use Srv\Apps\Proto\DTO\Content\ContentAddDTO;
use Srv\Apps\Proto\DTO\Content\ContentEditDTO;
use Srv\Apps\Proto\DTO\Content\ContentListDTO;
use Srv\Apps\Proto\Enum\YesOrNoEnum;
use Srv\Apps\Proto\VO\Content\ContentListVO;
use Srv\Apps\Proto\VO\Content\ContentVO;
use Srv\Libs\Common\CommArray;
use Srv\Libs\Common\CommString;
use Srv\Libs\Common\CommTime;
use Srv\Libs\Frame\ControllerAbstract;
use Srv\Libs\Frame\Page;
use Srv\Libs\Storage\DataMysql;

final class ContentCtl extends ControllerAbstract
{
    private ?DataMysql $DbAuto              = null;     // DB-Write
    private string $contentUrl              = 'https://wwwxc.nilela.com/shtml/{KEY}';
    private string $contentUrlGG            = 'https://wwwxc.nilela.com/tvshort/{KEY}';
    private string $contentUrlAppleHot      = 'https://wwwxc.nilela.com/hotshort/{KEY}';

    /**
     * @return static
     * tag
     */
    final public static function tag():self
    {
        $thisObject                         = self::tagGet();
        if($thisObject instanceof self){
            $thisObject->DbAuto             = self::getDbAuto();
        }
        if($thisObject->isRelease()){
            $thisObject->contentUrl         = 'https://www.xc.com/shtml/{KEY}';
            $thisObject->contentUrlGG       = 'https://www.xctvs.com/tvshort/{KEY}';
            $thisObject->contentUrlAppleHot = 'https://www.hotshort.cc/hotshort/{KEY}';
        }
        return $thisObject;
    }

    /**
     * @param int $cttrId
     * @return array
     * getContentSrc
     */
    public function getContentSrc(int $cttrId):array
    {
        if($cttrId < 1) return [];
        $isFail     = false;
        $info       = $this->DbAuto->getDataOne('SELECT cttr_id, cttr_key, cttr_type, cttr_title, cttr_content, cttr_status, cttr_create_time, cttr_update_time FROM '.$this->DbAuto->getTableNameAll('content_record').' WHERE cttr_id='.$cttrId.' AND cttr_delete=0', $isFail);
        if($isFail || !isset($info['cttr_id'])) return [];
        return $info;
    }

    /**
     * @param array $cttrIdList
     * @return array
     * getContentSrcBatch
     */
    public function getContentSrcBatch(array $cttrIdList):array
    {
        if(count($cttrIdList) < 1) return [];
        $isFail         = false;
        $list           = $this->DbAuto->getData('SELECT cttr_id, cttr_key, cttr_type, cttr_title, cttr_content, cttr_status, cttr_create_time, cttr_update_time FROM '.$this->DbAuto->getTableNameAll('content_record').' WHERE cttr_id IN('.implode(',', $cttrIdList).') AND cttr_delete=0', $isFail);
        $listData       = [];
        if(!$isFail && CommArray::isForeach($list)) foreach ($list as $item){
            $cttrIdItem             = intval($item['cttr_id']??0);
            if($cttrIdItem < 1) continue;
            $listData[$cttrIdItem]  = $item;
        }
        return $listData;
    }

    /**
     * @param array $cttrIdList
     * @return array
     * getContentSrcBatch
     */
    public function getContentBatch(array $cttrIdList):array
    {
        $list       = $this->getContentSrcBatch($cttrIdList);
        $listData   = [];
        if(CommArray::isForeach($list)){
            foreach ($list as $item){
                $cttrIdItem             = intval($item['cttr_id']??0);
                if($cttrIdItem < 1) continue;
                $ContentVO              = $this->getContentVO($item);
                if(!($ContentVO instanceof ContentVO)) continue;
                $listData[$cttrIdItem]  = $ContentVO;
            }
        }
        return $listData;
    }

    /**
     * @param Page $Page
     * @param array $whereData
     * @return ContentListVO|null
     * getContentList
     */
    public function getContentList(Page $Page, array $whereData): ?ContentListVO
    {
        $limitString        = $Page->getLimitString();
        $whereString        = ' WHERE cttr_delete=0 ';
        // 检索条件
        if(count($whereData) > 0)foreach ($whereData as $key => $val){
            switch ($key){
                case ContentListDTO::_cttrId:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'cttr_id='. intval($val);
                    break;
                case ContentListDTO::_title:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'cttr_title LIKE \'%'.$this->DbAuto->getRealEscapeString($val).'%\'';
                    break;
                case ContentListDTO::_key:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'cttr_key LIKE \'%'.$this->DbAuto->getRealEscapeString($val).'%\'';
                    break;
                case ContentListDTO::_status:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'cttr_status='. intval($val);
                    break;
                case ContentListDTO::_type:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'cttr_type='. intval($val);
                    break;
            }
        }
        $isFail             = false;
        $sql                = 'SELECT SQL_CALC_FOUND_ROWS cttr_id, cttr_key, cttr_type, cttr_title, cttr_content, cttr_status, cttr_create_time, cttr_update_time FROM '.$this->DbAuto->getTableNameAll('content_record').$whereString.' ORDER BY cttr_id DESC '.$limitString;
        $list               = $this->DbAuto->getData($sql, $isFail);
        $totalNum           = $this->DbAuto->getDataInt('SELECT FOUND_ROWS() as num', 'num');
        if($isFail) return null;
        $ContentVOList      = [];
        if(CommArray::isForeach($list)) foreach($list as $categoryRecord){
            $cttrIdItem         = intval($categoryRecord['cttr_id']);
            if($cttrIdItem < 1) continue;
            $ContentVO          = $this->getContentVO($categoryRecord);
            if(!($ContentVO instanceof ContentVO)) continue;
            $ContentVOList[]    = $ContentVO;
        }
        $ContentListVO          = new ContentListVO();
        $ContentListVO->setList($ContentVOList);
        $ContentListVO->setPage($Page->getPageVO($totalNum));
        return $ContentListVO;
    }

    /**
     * @param int $cttrId
     * @return ContentVO|null
     * getContentInfo
     */
    public function getContentInfo(int $cttrId):?ContentVO
    {
        $infoSrc    = $this->getContentSrc($cttrId);
        if(!isset($infoSrc['cttr_id'])) return null;
        return $this->getContentVO($infoSrc);
    }

    /**
     * @param array $info
     * @return ContentVO|null
     * getContentVO
     */
    public function getContentVO(array $info):?ContentVO
    {
        $cttrId             = intval($info['cttr_id']??0);
        if($cttrId < 1) return null;
        $ContentVO          = new ContentVO();
        $type               = intval($info['cttr_type']??0);
        $ContentVO->setCttrId($cttrId);
        $ContentVO->setTitle(trim($info['cttr_title']));
        $ContentVO->setKey(trim($info['cttr_key']));
        $ContentVO->setType(intval($info['cttr_type']));
        $ContentVO->setContent(trim($info['cttr_content']));
        $ContentVO->setStatus(YesOrNoEnum::parseValue($info['cttr_status']));
        $ContentVO->setCreateTime(intval($info['cttr_create_time']));
        $ContentVO->setUpdateTime(intval($info['cttr_update_time']));
        if($type === 1){
            $ContentVO->setUrl(str_replace('{KEY}', $ContentVO->getKey(), $this->contentUrlGG));
        }else if($type === 2){
            $ContentVO->setUrl(str_replace('{KEY}', $ContentVO->getKey(), $this->contentUrlAppleHot));
        }else{
            $ContentVO->setUrl(str_replace('{KEY}', $ContentVO->getKey(), $this->contentUrl));
        }
        return $ContentVO;
    }

    /**
     * @param array $setData
     * @return int
     * 新增内容
     */
    public function contentAdd(array $setData):int
    {
        if(count($setData) < 1) return 0;
        $setString      = '';
        foreach ($setData as $key => $val){
            switch ($key){
                case ContentAddDTO::_title:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'cttr_title=\''.$this->DbAuto->getRealEscapeString($val).'\'';
                    break;
                case ContentAddDTO::_type:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'cttr_type='.intval($val);
                    break;
                case ContentAddDTO::_content:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'cttr_content=\''.$this->DbAuto->getRealEscapeString($val).'\'';
                    break;
                case ContentAddDTO::_status:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'cttr_status='.intval($val);
                    break;
                case ContentAddDTO::_key:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'cttr_key=\''.$this->DbAuto->getRealEscapeString($val).'\'';
                    break;
            }
        }
        if(strlen($setString) < 1) return 0;
        $currTime       = CommTime::getTimeStamp(0);
        $isFail         = false;
        $sql            = 'INSERT INTO '.$this->DbAuto->getTableNameAll('content_record').' SET '.$setString.', cttr_delete=0, cttr_create_time='.$currTime.', cttr_update_time='.$currTime;
        $cttrId         = $this->DbAuto->getDataId($sql, $isFail);
        if($isFail || $cttrId < 1) return 0;
        return $cttrId;
    }

    /**
     * @param int $cttrId
     * @param array $setData
     * @return bool
     * 编辑内容
     */
    public function contentEdit(int $cttrId, array $setData):bool
    {
        if($cttrId < 1 || count($setData) < 1) return false;
        $setString      = '';
        foreach ($setData as $key => $val){
            switch ($key){
                case ContentEditDTO::_title:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'cttr_title=\''.$this->DbAuto->getRealEscapeString($val).'\'';
                    break;
                case ContentEditDTO::_type:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'cttr_type='.intval($val);
                    break;
                case ContentEditDTO::_key:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'cttr_key=\''.$this->DbAuto->getRealEscapeString($val).'\'';
                    break;
                case ContentEditDTO::_content:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'cttr_content=\''.$this->DbAuto->getRealEscapeString($val).'\'';
                    break;
                case ContentEditDTO::_status:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'cttr_status='.intval($val);
                    break;
            }
        }
        if(strlen($setString) < 1) return false;
        $isFail         = false;
        $currTime       = CommTime::getTimeStamp(0);
        $sql            = 'UPDATE '.$this->DbAuto->getTableNameAll('content_record').' SET '.$setString.', cttr_update_time='.$currTime.' WHERE cttr_id='.$cttrId.' AND cttr_delete=0';
        if($this->DbAuto->getDataNum($sql, $isFail) < 1 || $isFail) return false;
        return true;
    }

    /**
     * @return string
     * getSkitInfoKey
     */
    public function getContentKey():string
    {
        $minLength          = 8;        // 最小长度
        $maxLength          = 16;       // 最大长度
        $maxNum             = 200;
        $currNum            = 1;
        $indexNum           = 1;
        $randKey            = strtolower(CommString::genRandStr($minLength));
        while($currNum <= $maxNum){
            $IdFind         = $this->DbAuto->getDataInt('SELECT cttr_id FROM '.$this->DbAuto->getTableNameAll('content_record').' WHERE binary cttr_key=\''.$this->DbAuto->getRealEscapeString($randKey).'\'', 'cttr_id');
            if($IdFind < 1) break;
            if($indexNum >= 50){                // 失败自增长度1
                $indexNum   = 0;
                $minLength  += 1;
            }
            if($minLength > $maxLength) break;  // 长度封顶
            $randKey        = strtolower(CommString::genRandStr($minLength));
            ++$indexNum;
            ++$currNum;
        }
        return $randKey;
    }
}